package org.ihelpuoo.weboo.module;

import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.ihelpuoo.core.Nut;
import org.ihelpuoo.lang.NutException;
import org.ihelpuoo.parser.segment.SegmentFactory;
import org.ihelpuoo.util.Properties;
import org.ihelpuoo.util.ValueSet;
import org.ihelpuoo.weboo.Messager;
import org.ihelpuoo.weboo.action.http.Action;
import org.ihelpuoo.weboo.exception.ActionConfigInvalidException;
import org.ihelpuoo.weboo.exception.ActionInstanceException;
import org.ihelpuoo.weboo.exception.ActionNotFoundException;
import org.ihelpuoo.weboo.security.SessionImpl;
import org.ihelpuoo.weboo.util.XMLPatternFactory;

public class ModuleContext
{
	private Map<Object, Object>					attributes;
	private ModuleManager						moduleManager;
	private WebooConfig							webooConfig;
	private Properties							config;
	private Messager							messager;
	private Nut									nut;
	private Module								module;
	private String								styleHome;
	private ModuleProperties					_properties;
	private ModuleAttributes					_atts;
	private Map<Locale, XMLPatternFactory>	ptnfacs;

	public ModuleContext(Nut nut, ModuleManager moduleManager, WebooConfig config)
	{
		this.moduleManager = moduleManager;
		this.webooConfig = config;
		this.nut = nut;
		ptnfacs = new HashMap<Locale, XMLPatternFactory>();
	}

	public SegmentFactory patterns(Locale locale)
	{
		XMLPatternFactory sf = ptnfacs.get(locale);
		if (null == sf)
		{
			synchronized (this)
			{
				sf = ptnfacs.get(locale);
				if (null == sf)
				{
					sf = new XMLPatternFactory(this,locale);
					sf.setNut(nut);
					try
					{
						sf.init(webooConfig.getPatternSetting());
					}
					catch (NutException e)
					{
						throw new RuntimeException(e);
					}
					ptnfacs.put(locale,sf);
				}
			}
		}
		return sf;
	}

	public SegmentFactory patterns(HttpServletRequest request)
	{
		return patterns(SessionImpl.wrap(request).getLocale());
	}

	public List<Locale> getLocales()
	{
		if (null == messager)
			return null;
		return ((WebooMessager)messager).getLocales();
	}

	public ServletContext getServletContext()
	{
		return this.moduleManager.servletContext;
	}

	void setStyleHome(String cssHome)
	{
		this.styleHome = cssHome;
	}

	public String getStyleHome()
	{
		return styleHome;
	}

	public String getModuleName()
	{
		return module.getName();
	}

	public Module getModule()
	{
		return module;
	}

	void setModule(Module module)
	{
		this.module = module;
	}

	Charset getInputCharset()
	{
		return module.getInputCharset();
	}

	Charset getOutputCharset()
	{
		return module.getOutputCharset();
	}

	void setMessager(String messageFileName)
	{
		if (null == messageFileName)
			messager = null;
		else
		{
			messager = new WebooMessager(messageFileName);
			((WebooMessager)messager).initLocales(webooConfig.isEscapedMessage());
		}
	}

	public Messager getMessager()
	{
		return messager;
	}

	public ModuleManager getModuleManager()
	{
		return moduleManager;
	}

	public Properties getConfig()
	{
		return config;
	}

	void setConfig(Properties myConfig)
	{
		this.config = myConfig;
	}

	public ActionManager actions()
	{
		return module.getActionManager();
	}

	public Action getAction(String name) throws ActionNotFoundException, ActionInstanceException
	{
		return module.getActionManager().getAction(name);
	}

	public ActionConfig getActionConfig(String name) throws ActionConfigInvalidException
	{
		return module.getActionManager().getActionConfig(name);
	}

	public WebooConfig getWebooConfig()
	{
		return webooConfig;
	}

	public Nut nut()
	{
		return nut;
	}

	public ModuleInstaller installer()
	{
		return module.getInstaller();
	}

	public Object getAttributes(Object key)
	{
		if (null == attributes)
		{
			attributes = new HashMap<Object, Object>();
		}
		return attributes.get(key);
	}

	public ValueSet attributes()
	{
		if (this._atts == null)
			this._atts = new ModuleAttributes(this);
		return this._atts;
	}

	public ValueSet properties()
	{
		if (this._properties == null)
			this._properties = new ModuleProperties(this);
		return this._properties;
	}

	public void setAttributes(Object key, Object value)
	{
		if (null == attributes)
		{
			attributes = new HashMap<Object, Object>();
		}
		attributes.put(key,value);
	}

	public String getMessage(Locale locale, String key)
	{
		String msg = null;
		if (null != messager)
		{
			msg = messager.getMessage(locale,key);
			if (null == msg)
				msg = getMessageFromDefaultModuleMessager(locale,key);
		}
		else
			msg = getMessageFromDefaultModuleMessager(locale,key);
		return msg;
	}

	private String getMessageFromDefaultModuleMessager(Locale locale, String key)
	{
		String msg = getDefaultMessager().getMessage(locale,key);
		if (null == msg)
			return key;
		return msg;
	}

	public Messager getDefaultMessager()
	{
		return this.getModuleManager().getDefaultModule().getModuleContext().messager;
	}

}
